/*
 * Client.c
 * 
 */

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <Message.h>

void encode(Message_t *message, char *data, int number, char *string)
{
	free(message);
	message = calloc(1, sizeof(Message_t));
	message->num = number;
	OCTET_STRING_fromBuf(&message->str, string, -1);
	asn_enc_rval_t ec = der_encode_to_buffer(&asn_DEF_Message, message, data, 1024); 
	if(ec.encoded == -1)
	{
		perror("der_encode_to_buffer");
		exit(65);
	}
}

void decode(Message_t *message, char *data)
{
	free(message);
	message = calloc(1, sizeof(Message_t));
	asn_dec_rval_t dc = ber_decode(0, &asn_DEF_Message, (void **)&message, data, 1024);
	if(dc.code != RC_OK)
	{
		perror("ber_decode");
		exit(65);
	}
}

void print(char *shell, char *data, Message_t *message, int isHex)
{
	printf("%s: %d %s \n", shell, message->num, message->str.buf);
	if(isHex)
	{
		int i = 0;
		for(; i < strlen(data); i++) printf("%#.2x ", data[i]);
		printf("\n");
	}
}

int main(int argc, char *argv[])
{
	int sock, bytes_received, invalid, i; 
	uint8_t send_data[1024], recv_data[1024];
	struct hostent *host;
	struct sockaddr_in server_addr;  
	Message_t *message = calloc(1, sizeof(Message_t));
		
	host = gethostbyname("127.0.0.1");

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("Socket");
		exit(1);
	}

	server_addr.sin_family = AF_INET;     
	server_addr.sin_port = htons(5000);   
	server_addr.sin_addr = *((struct in_addr *)host->h_addr);
	bzero(&(server_addr.sin_zero),8); 

	if (connect(sock, (struct sockaddr *)&server_addr,
		sizeof(struct sockaddr)) == -1) 
	{
		perror("Connect");
		exit(1);
	}
	else
	{
		printf("Connected with server 127.0.0.1:5000\n");
	}

	while(1)
	{
		// examine the input
		do{
			invalid = 0;
			printf("Please input a number(q or Q to quit): ");
			//gets(send_data);
			scanf("%s", send_data);
			// quit the program
			if (strcmp(send_data , "q") == 0 || strcmp(send_data , "Q") == 0)
			{
				close(sock);
				exit(0);
			}
			// make sure the input is an integer
			for(i = 0; i < strlen(send_data); i++) {
				if(send_data[i] < '0' || send_data[i] > '9'){
					invalid = 1;
					break;
				}
			}
		}while(invalid);
		
		// send the integer to the server
		encode(message, send_data, atoi(send_data), "");
		send(sock,send_data,strlen(send_data), 0); 
		print("Send data", send_data, message, argc > 1);
					
		// receive the feedback from the server
		if((bytes_received = recv(sock, recv_data, 1024, 0)) <= 0)
		{
			printf("Server closed\n");
			close(sock);
			exit(1);
		}
		recv_data[bytes_received] = '\0';
		decode(message, recv_data);
		print("Received data", recv_data, message, argc > 1);
			   
		// process the string
		printf("Do you want to send the corect response? (Y for yes, N for No): ");
		//gets(send_data);
		scanf("%s", send_data);
		if(strcmp(send_data , "Y") == 0)
		{
			// send the correct string
			i = 0;
			/*while(recv_data[i] != ' ') i++;
			int string_begin = ++i;
			for(; i < strlen(recv_data); i++)
			{
				if(recv_data[i] >= 'a' && recv_data[i] <= 'z') send_data[i - string_begin] = recv_data[i] - 32;
				else if(recv_data[i] >= 'A' && recv_data[i] <= 'Z') send_data[i - string_begin] = recv_data[i] + 32;
				else send_data[i - string_begin] = recv_data[i];
			}
			send_data[i - string_begin] = '\0';*/
			for(; i < strlen(message->str.buf); i++)
			{
				if(message->str.buf[i] >= 'a' && message->str.buf[i] <= 'z') send_data[i] = message->str.buf[i] - 32;
				else if(message->str.buf[i] >= 'A' && message->str.buf[i] <= 'Z') send_data[i] = message->str.buf[i] + 32;
				else send_data[i] = message->str.buf[i];
			}
			send_data[i] = '\0';
		}
		else
		{
			// send a wrong string
			i = 0;
			/*while(recv_data[i] != ' ') i++;
			int string_begin = ++i;
			for(; i < strlen(recv_data); i++)
			{
				send_data[i - string_begin] = 'x';
			}
			send_data[i - string_begin] = '\0';*/
			for(; i < strlen(message->str.buf); i++)
			{
				send_data[i] = 'x';
			}
			send_data[i] = '\0';
		}
		encode(message, send_data, message->num, send_data);
		send(sock, send_data, strlen(send_data), 0);
		print("Send data", send_data, message, argc > 1);
		
		// receive the verification of the string
		if((bytes_received = recv(sock, recv_data, 1024, 0)) <= 0)
		{
			printf("Server closed\n");
			close(sock);
			exit(1);
		}
		recv_data[bytes_received] = '\0';
		decode(message, recv_data);
		print("Received data", recv_data, message, argc > 1);
	}   
	return 0;
}
